package com.shisan.tingshu.search.runners;

import com.shisan.tingshu.search.service.impl.ItemServiceImpl;
import org.redisson.api.RBloomFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.List;


/**
 * 利用SpringBoot的Runnner机制完成对分布式布隆过滤器的元素同步
 * ApplicationRunner：
 * 实现ApplicationRunner接口的类会在SpringBoot应用启动后被调用，run()方法会接收一个ApplicationArguments对象，可以用来获取应用启动时的命令行参数等信息；
 * 这种方式通常用于在应用启动后执行一些需要访问应用参数的初始化操作；
 * CommandLineRunner：
 * 与ApplicationRunner类似，实现CommandLineRunner接口的类也会在应用启动后被调用，run()方法接收的是原始的命令行参数数组；
 * 如果只需要简单地处理命令行参数，而不需要ApplicationArguments提供的高级功能，那么可以使用CommandLineRunner；
 */
//@Component
public class BloomFilterRunners implements ApplicationRunner, CommandLineRunner, ApplicationContextAware {

    // 定义一个ApplicationContextAware接口的实现类，用于获取spring容器中的Bean对象
    private ApplicationContext applicationContext;

    Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * ApplicationRunner 接口的run()方法会在SpringBoot应用启动后被调用，run()方法接收一个ApplicationArguments对象，可以用来获取应用启动时的命令行参数等信息
     * 这些参数中：--表示可选参数，没有--的表示必选参数。比如：--spring.profiles.active=dev表示可选参数，spring.profiles.active=dev表示必选参数
     * 在该方法中，可以获取到布隆过滤器的Bean对象，然后将数据同步到布隆过滤器中
     * @param args
     * @throws Exception
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {

//        Set<String> optionNames = args.getOptionNames();
//        for (String optionName : optionNames) { // 获取可选参数
//            System.out.println("命令行中输入的可选参数名：" + optionName + "值：" + args.getOptionValues(optionName));
//        }
//        for (String nonOptionArg : args.getNonOptionArgs()) { // 获取必选参数
//            System.out.println("命令行中输入的必选参数名：" + nonOptionArg + "值：" + args.getOptionValues(nonOptionArg));
//        }
        // 从Spring容器中获取到布隆过滤器的Bean对象
        RBloomFilter rBloomFilter = applicationContext.getBean("rBloomFilter", RBloomFilter.class);
        // 从Spring容器中获取应用的Bean对象
        ItemServiceImpl itemServiceImpl = applicationContext.getBean("itemServiceImpl", ItemServiceImpl.class);
        // 获取数据
        List<Long> albumInfoIdList = itemServiceImpl.getAlbumInfoIdList();
        // 将数据放到布隆过滤器中
        for (Long albumId : albumInfoIdList) {
            rBloomFilter.add(albumId);
        }
        // 打印日志，判断布隆过滤器元素是否同步进去
        logger.info("分布式布隆过滤器的元素个数：" + rBloomFilter.count());
    }

    /**
     * CommandLineRunner 接口的run()方法会在SpringBoot应用启动后被调用，run()方法接收的是原始的命令行参数数组
     * @param args
     * @throws Exception
     */
    @Override
    public void run(String... args) throws Exception {

    }

    /**
     * 实现ApplicationContextAware接口，用于获取spring容器中的Bean对象
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

        this.applicationContext = applicationContext;
    }
}
